import { PropType, ref, defineComponent, watchEffect, App, Plugin, h, resolveComponent, renderSlot } from 'vue'
import { DownOutlined, SettingOutlined } from '@ant-design/icons-vue'
import { isEmpty, isNil, map, forEach, find, equals } from 'ramda'
import { chunk, isString } from '@/utils/tools'
import { clone } from 'ramda'
import { JSX } from 'vue/jsx-runtime'
/**
 * @user: antes
 * @emial: tangzhlyd@gmail.com
 * @data: 2021/7/22 下午3:58
 */
type ObjectMap<Key extends string | number | symbol = any, Value = any> = {
	[key in Key]: Value
}
interface LabelCol {
	span?: number
	offset?: number
}
interface RowConf {
	key: string
	title: string
	sort?: number
	required?: boolean
	show?: boolean
	colSpan?: number
	wrapperCol?: LabelCol
	modelValue?: string
}
export interface Row extends RowConf {
	render?: () => JSX.Element
	component?: any
	slotName?: string
	props?: ObjectMap
}
const Props = {
	labelCol: {
		type: Object as PropType<LabelCol>,
		default: () => {
			return { span: 6 }
		},
	},
	wrapperCol: {
		type: Object as PropType<LabelCol>,
		default: () => {
			return { span: 16 }
		},
	},
	model: {
		type: Object as PropType<ObjectMap>,
		required: true,
	},
	layout: {
		type: String as PropType<'horizontal' | 'vertical' | 'inline'>,
		default: 'horizontal',
	},
	rows: {
		type: Array as PropType<Row[]>,
		required: true,
	},
	expand: Object as PropType<{
		expandToggle: () => void
		value: boolean
	}>,
	lineLength: {
		type: Number as PropType<number>,
		default: 3,
	},
	clear: {
		type: Function as PropType<() => void>,
		required: true,
	},
	search: {
		type: Function as PropType<() => void>,
		required: true,
	},
	loading: Boolean as PropType<boolean>,
	searchKey: {
		type: String as PropType<string>,
		required: true,
	},
} as const
const FSearch = defineComponent({
	name: 'f-search',
	props: Props,
	setup(props, { slots }) {
		const customRow = ref<RowConf[]>([]) // 用户自定义的
		const customRowStr = localStorage.getItem(props.searchKey + '-search')
		if (customRowStr) {
			customRow.value = JSON.parse(customRowStr)
		}
		initCustomRow()
		function initCustomRow() {
			if (isEmpty(customRow.value)) {
				customRow.value = props.rows.map((item, index) => {
					// const data = find((res) => equals(res.key, item.key), customRow.value)
					const required = isNil(item.required) ? false : item.required
					const show = required ? true : isNil(item.show) ? index < props.lineLength : item.show
					return {
						key: item.key,
						title: item.title,
						sort: index,
						required,
						show,
						colSpan: item.colSpan ?? 6,
					}
				})
			}
		}
		const visible = ref(false)
		const rows = ref<Row[][]>([]) // 过滤之后的
		function custom() {
			visible.value = true
		}
		watchEffect(() => {
			const list: Row[] = []
			forEach((item) => {
				if (item.show) {
					const data = find((res) => equals(res.key, item.key), props.rows)
					data && list.push(data)
				}
			}, customRow.value)
			rows.value = props.expand ? chunk(list, props.lineLength) : [list]
		})

		function submit(row: RowConf[]) {
			customRow.value = row
			initCustomRow()
			localStorage.setItem(props.searchKey + '-search', JSON.stringify(row))
		}
		// function renderRow(row: Row) {
		// 	console.log('渲染')
		// 	if (row.render) {
		// 		return (
		// 			<a-form-item label={row.title} name={row.key}>
		// 				{row.render()}
		// 			</a-form-item>
		// 		)
		// 	} else if (row.component) {
		// 		const modelValue = row.modelValue ?? 'value'
		// 		if (isString(row.component)) {
		// 			return (
		// 				<a-form-item label={row.title} name={row.key}>
		// 					{h(resolveComponent(row.component), {
		// 						...row.props,
		// 						[modelValue]: props.model[row.key],
		// 						[`onUpdate:${modelValue}`]: ($event: any) => (props.model[row.key] = $event)
		// 					})}
		// 				</a-form-item>
		// 			)
		// 		} else {
		// 			return (
		// 				<a-form-item label={row.title} name={row.key}>
		// 					{h(row.component, {
		// 						...row.props,
		// 						[modelValue]: props.model[row.key],
		// 						[`onUpdate:${modelValue}`]: ($event: any) => (props.model[row.key] = $event)
		// 					})}
		// 					{/*// <row.component allowClear {...row.props} v-model={[props.model[row.key], 'value']} />*/}
		// 				</a-form-item>
		// 			)
		// 		}
		// 	}
		// }
		return () => {
			return (
				<>
					<div class="top-search-from-nowidth top-search-from">
						{renderSlot(slots, 'header')}
						<div>
							<a-form className="ant-advanced-search-form" labelCol={props.labelCol} wrapperCol={props.wrapperCol}>
								<a-row>
									{rows.value.map((item, index) => {
										if (index > 0 && props.expand) {
											return props.expand.value ? (
												<>
													{map(
														(row) => (
															<a-col span={row.colSpan ?? 6} key={row.key}>
																{row.render ? (
																	row.render()
																) : row.slotName && slots[row.slotName] ? (
																	renderSlot(slots, row.slotName)
																) : (
																	<a-form-item label={row.title} name={row.key} {...{ wrapperCol: row.wrapperCol }}>
																		{h(isString(row.component) ? resolveComponent(row.component) : row.component, {
																			...row.props,
																			[row.modelValue ?? 'value']: props.model[row.key],
																			[`onUpdate:${row.modelValue ?? 'value'}`]: ($event: any) =>
																				// eslint-disable-next-line vue/no-mutating-props
																				(props.model[row.key] = $event),
																		})}
																	</a-form-item>
																)}
															</a-col>
														),
														item
													)}
												</>
											) : null
										} else {
											return map(
												(row) => (
													<a-col span={row.colSpan ?? 6} key={row.key}>
														{row.render ? (
															row.render()
														) : row.slotName && slots[row.slotName] ? (
															renderSlot(slots, row.slotName)
														) : (
															<a-form-item label={row.title} name={row.key} {...{ wrapperCol: row.wrapperCol }}>
																{h(isString(row.component) ? resolveComponent(row.component) : row.component, {
																	...row.props,
																	[row.modelValue ?? 'value']: props.model[row.key],
																	[`onUpdate:${row.modelValue ?? 'value'}`]: ($event: any) =>
																		// eslint-disable-next-line vue/no-mutating-props
																		(props.model[row.key] = $event),
																})}
															</a-form-item>
														)}
													</a-col>
												),
												item
											)
										}
									})}
									<a-col span={6}>
										<a-form-item style="padding-left:10px">
											<a-button type="primary" loading={props.loading} onClick={props.search}>
												查询
											</a-button>
											<a-button onClick={props.clear}>清除</a-button>
											{props.expand && rows.value.length > 1 && (
												<a class="expand" onClick={props.expand.expandToggle}>
													<DownOutlined rotate={props.expand.value ? 180 : 0} />
													{props.expand.value ? '收起' : '更多'}
												</a>
											)}
											<a class="expand" onClick={custom}>
												<a-tooltip placement="topLeft" title="自定义显示">
													<SettingOutlined />
												</a-tooltip>
											</a>
										</a-form-item>
									</a-col>
								</a-row>
							</a-form>
						</div>
					</div>
					<f-configure
						v-model={visible.value}
						onSubmit={submit}
						title="查询条件调整自定义"
						columns={clone(customRow.value)}
					/>
				</>
			)
		}
	},
})

FSearch.install = function (app: App) {
	app.component(FSearch.name as string , FSearch)
	return app
}
export default FSearch as typeof FSearch & Plugin
